OTG接口介绍及使用示例
修订日期 | 修订版本 | 修订内容 | 修订人 |
---|---|---|---|
2024.02.27 | V0.1 | 初始化文档 | 赵锦强 |
[TOC]
1 简介
OTG: Online Trajectory Generation, 在线轨迹生成算法。可以针对多自由度系统从任意的初始状态,受最大的速度、加速度和加加速度限制下,规划出到任意目标状态的时间最优轨迹,具有实时计算能力。计算结果是位置、速度、加速度和加加速度随时间变化的曲线,例如下图所示:
2 实例化对象及速度规划接口
2.1 调用如下接口,实例化otg对象
/**
* @brief 构造函数
* @param dim: 规划的自由度个数
* @param cycleTimeInSeconds: 规划周期
* @param type: OTG算法的类型,可使用默认值
* @param mode: OTG算法的运动模式,分为位置模式和速度模式
* @param sync: OTG算法的多自由度运动同步模式,包含相位同步、时间同步、不同步,可使用默认值
*/
OTGInterface(const unsigned int& dim, const double& cycleTimeInSeconds, const OTGType& type = OTGType::TypeV,
const MoveMode& mode = MoveMode::POSITION, const SyncBehavior& sync = SyncBehavior::PHASE_SYNCHRONIZATION_IF_POSSIBLE);
2.2 调用如下接口,设置运动参数,计算速度轮廓,一般在实例化对象后调用
/**
* @brief 设置运动参数, 计算速度轮廓
* @param maxV: 运动最大速度约束
* @param minV: 运动最小速度约束
* @param maxA: 运动最大加速度约束
* @param minA: 运动最小加速度约束
* @param maxJ: 运动最大加加速度约束
* @param curP: 当前运动位置
* @param curV: 当前运动速度
* @param curA: 当前运动加速度
* @param tarP: 目标运动位置
* @param tarV: 目标运动速度
* @param tarA: 目标运动加速度
* @param moveTime: 用户设置的整个运动过程时间,实际的运动时间不小于设定值
* @return if < 0, 表示运动计算失败
*/
int setMotionParameters(const double* maxV, const double* minV, const double* maxA, const double* minA,const double* maxJ, const double* curP, const double* curV, const double* curA,const double* targetP, const double* targetV, const double* targetA, const double moveTime = 0);
2.3 调用如下接口,单独设置速度规划的约束条件,会触发重新计算速度轮廓,适用于运动约束动态变化的场景
/**
* @brief 设置速度规划的约束条件(会触发重新计算速度轮廓, 适用于运动约束动态变化的场景)
* @param maxVel: 最大速度
* @param maxAcc: 最大加速度
* @param maxJ: 最大加加速度
* @return if < 0, 表示速度规划失败
*/
int setConstraints(const double* maxVel, const double* maxAcc, const double* maxJ);
2.4 调用如下接口,更新目标状态,会触发重新计算速度轮廓, 适用于目标跟踪场景
/**
* @brief 更新目标状态(会触发重新计算速度轮廓, 适用于目标跟踪场景)
* @param tarPos: 目标位置
* @param tarVel: 目标速度
* @param tarAcc: 目标加速度
* @return if < 0, 表示速度规划失败
*/
int updateTargetStates(const double* tarPos, const double* tarVel, const double* tarAcc);
3 采样接口
3.1 调用如下接口,按指定的时间间隔插值得到位置、速度、加速度
/**
* @brief 按指定的时间间隔插值得到位置、速度、加速度信息,时间单位:s
* @param posTraj: 采样位置
* @param velTraj: 采样速度
* @param accTraj: 采样加速度
* @param stepTime:采样时间间隔
* @return if = 0, 表示正常采样,if = 1, 表示采到终点,采样结束
*/
int otgStep(double* posTraj, double* velTraj, double* accTraj, const double stepTime = 0);
3.2 调用如下接口,计算给定时刻的轨迹信息
/**
* @brief 计算在某个时刻的位置,速度和加速度
* @param timeValueInSeconds: 给定时刻
* @param posTraj: 位置
* @param velTraj: 速度
* @param accTraj: 加速度
* @return if = 0, 表示正常采样,if = 1, 表示采到终点,采样结束
*/
int otgPVA(const double& timeValueInSeconds, double* posTraj, double* velTraj, double* accTraj);
4 速度轮廓信息获取
接口 | 描述 |
---|---|
getDuration | 获取速度轮廓总的运动时间 |
getDimension | 获取速度规划的维度(自由度个数) |
getMonotoneIncreasingFlag | 判断规划出的位置曲线是否单调递增 |
/**
* @brief 指定某个自由度,指定位置,获取对应的时间t, 速度v, 和加速度a(调用该函数时需保证位置随着时间单调递增)
* @param index: 指定第index个维度
* @param S: 给定一系列位置点
* @param T: 获取对应的时间点
* @param V: 获取对应的速度
* @param A: 获取对应的加速度
* @return if < 0, 表示计算失败
*/
int calTVAGivenPos(const int index, const std::vector<double>& S, std::vector<double>& T, std::vector<double>& V, std::vector<double>& A);
5 使用示例
//! 设置运动参数
std::vector<double> pos1, vel1, acc1, posT, velT, accT, maxV, maxA, minA, maxJ;
if(type == 1)
{
//起始状态
pos1 = {0.0, 0.0};
vel1 = {2.13378, 0.682608};
acc1 = {4.073, 0.0};
//目标状态
posT = {0.456938, 0.290321};
velT = {0.0, 0.0};
accT = {0.0, 0.0};
//运动约束
maxV = {0.9, 0.9};
maxA = {10, 15};
maxJ = {320, 48};
}
//!实例化otg对象
int DOF = 2;
double sample_period = 0.0005;
otg::OTGInterfacePtr otg(new otg::OTGInterface(DOF, sample_period, otg::OTGType::TypeV, otg::MoveMode::POSITION, otg::SyncBehavior::PHASE_SYNCHRONIZATION_IF_POSSIBLE));
//!设置运动参数,计算速度轮廓
int ret = otg->setMotionParameters(maxV.data(), nullptr, maxA.data(), nullptr, maxJ.data(), pos1.data(), vel1.data(), acc1.data(), posT.data(), velT.data(), accT.data());
//!采样,可以使用otgStep和otgPVA任意一种,下面提供了使用示例
#if 0
//otgPVA使用示例
int dof = otg->getDimension();
double duration = otg->getDuration();
double sample_period = 0.005;
std::vector<std::vector<double>> T, P, V, A;
std::vector<double> posTraj(dof), velTraj(dof), accTraj(dof);
double time = 0;
do
{
otg->otgPVA(time, posTraj.data(), velTraj.data(), accTraj.data());
for(int i = 0; i < dof; i++)
{
P[i].push_back(posTraj[i]);
V[i].push_back(velTraj[i]);
A[i].push_back(accTraj[i]);
}
T.push_back(time);
if(time == duration)
break;
time += sample_period;
if(time > duration)
time = duration;
}
while (time <= duration);
#else
//otgStep使用示例
double duration = otg->getDuration();
double sample_period = 0.005;
std::vector<double> time_series;
std::vector<double> S[DOF], V[DOF], A[DOF];
double posTraj[DOF];
double velTraj[DOF];
double accTraj[DOF];
double total_time = 0;
double step_time = 0;
int time_num = std::floor(duration / sample_period);
for(int i = 0; i <= time_num + 1; i++)
{
if(i == 0)
{
step_time = 0;
}
else if(i == time_num + 1)
{
step_time = duration - sample_period * time_num;
}
else
{
step_time = sample_period;
}
total_time = total_time + step_time;
otg->otgStep(posTraj, velTraj, accTraj, step_time);
time_series.push_back(total_time);
for(int j = 0; j < DOF; j++)
{
S[j].push_back(posTraj[j]);
V[j].push_back(velTraj[j]);
A[j].push_back(accTraj[j]);
}
}
#endif
//! 测试给定位置,计算对应的时间、速度和加速度
std::vector<double> pos = {pos1[0], (pos1[0] + posT[0]) / 2, posT[0]}, tt, vel, acc;
ret = otg->calTVAGivenPos(0, pos, tt, vel, acc);
//! 设置速度规划的约束条件,触发重新计算速度轮廓
maxV = {0.5, 1.0};
ret = otg->setConstraints(maxV.data(), nullptr nullptr); //只有最大速度发生改变
//!更新目标状态, 触发重新计算速度轮廓
posT = {0.856938, 0.590321};
velT = {0.0, 0.0};
accT = {0.0, 0.0};
ret = otg->updateTargetStates(posT.data(), velT.data(), accT.data());